import random
from threading import Thread
from ProtocolDefine import GameDefineProtocol
from collections import deque
from chess_utils import ChessPiece,ChessBoard
import time

notify = GameDefineProtocol().GameNotify()

class GameThread(Thread):
    
    def __init__(self):
        Thread.__init__(self)
        self.running = True        
        
    def run(self):
        while self.running:
            self.processRequest()
            self.processGameEvent()
            self.processResponse()
            time.sleep(1)
    
    def processRequest(self):
        pass
    
    def processResponse(self):
        pass
    
    def processGameEvent(self):
        pass
    
    def stop(self):
        self.running = False
        #print "Stop Thread"

class ChessGame(GameThread):
    RequestList = []
    ResponseList = []
    MAX_USER = 2
    
    def __init__(self,host=None,betmoney=None,password=None):
        self.userlist = []
        self.userlistcurrent = []        
        self.authenticated = False
        self.usercards = []
        self.userscore = []
        self.userwinners = []
        #self.deck = []
        self.chessboard = ChessBoard() 
        self.status = None
        #self.statusUser = dict()
        self.statusPlayingUser = dict()
        self.protocoldict = dict()
        self.host = host
        self.currentturn = -1
        self.betmoney = betmoney
        self.password = password
        GameThread.__init__(self)        
        self.initboard()
    
    def initboard(self):        
        #solider
        BSolider = ChessPiece("S","B",None) #black soldier
        WSolider = ChessPiece("S","W",None) #white soldier
        self.chessboard.set_piece(WSolider,("a",4))
        self.chessboard.set_piece(WSolider,("c",4))
        self.chessboard.set_piece(WSolider,("e",4))
        self.chessboard.set_piece(WSolider,("g",4))
        self.chessboard.set_piece(WSolider,("i",4))
        self.chessboard.set_piece(BSolider,("a",7))
        self.chessboard.set_piece(BSolider,("c",7))
        self.chessboard.set_piece(BSolider,("e",7))
        self.chessboard.set_piece(BSolider,("g",7))
        self.chessboard.set_piece(BSolider,("i",7))
        #cannon
        BCannon = ChessPiece("C","B",None) #black cannon
        WCannon = ChessPiece("C","W",None) #black cannon
        self.chessboard.set_piece(WCannon,("b",3))
        self.chessboard.set_piece(WCannon,("h",3))
        self.chessboard.set_piece(WCannon,("b",8))
        self.chessboard.set_piece(WCannon,("h",8))
        #chariot
        BRock = ChessPiece("R","B",None) #black chariot
        WRock = ChessPiece("R","W",None) #black chariot
        self.chessboard.set_piece(WRock,("a",1))
        self.chessboard.set_piece(WRock,("i",1))
        self.chessboard.set_piece(WRock,("a",10))
        self.chessboard.set_piece(WRock,("i",10))
        #knight
        BKnight = ChessPiece("K","B",None) #black knight
        WKnight = ChessPiece("K","W",None) #white knight
        self.chessboard.set_piece(WKnight,("b",1))
        self.chessboard.set_piece(WKnight,("h",1))        
        self.chessboard.set_piece(WRock,("b",10))
        self.chessboard.set_piece(WRock,("h",10))
        #elephant
        BElephant = ChessPiece("E","B",None) #black elephant
        WElephant = ChessPiece("E","W",None) #white elephant
        self.chessboard.set_piece(WElephant,("c",1))
        self.chessboard.set_piece(WElephant,("g",1))
        self.chessboard.set_piece(BElephant,("c",10))
        self.chessboard.set_piece(BElephant,("g",10))
        #advisor
        BAdvisor = ChessPiece("A","B",None) #black advisor
        WAdvisor = ChessPiece("A","W",None) #white advisor
        self.chessboard.set_piece(WAdvisor,("d",1))
        self.chessboard.set_piece(WAdvisor,("f",1))
        self.chessboard.set_piece(BAdvisor,("d",10))
        self.chessboard.set_piece(BAdvisor,("f",10))        
        #general
        BGeneral = ChessPiece("G","B",None) #black general
        WGeneral = ChessPiece("G","W",None) #white general
        self.chessboard.set_piece(WGeneral,("e",1))
        self.chessboard.set_piece(WGeneral,("e",10))

    def addRequest(self,request):
        self.RequestList.append(request)
        
    def addResponse(self,response):
        self.ResponseList.append(response)
    
    
    def processResponse(self):
        if len(self.ResponseList)>0:
            queue = deque(self.ResponseList)
            while True:
                try:                
                    user,res = queue.popleft()
                    if self.protocoldict.has_key(user):
                        self.protocoldict[user].response(res)
                except Exception as err:
                    break
            del self.ResponseList[:]    

    def join(self,user,protocol,password):
        global notify
        res = notify
        #check password
        if self.password:
            if password <> self.password:
                return False
        #check max user
        if len(self.userlist)>=self.MAX_USER:
            return False
        #append user in list                                
        self.userlist.append(user)
        self.usercards.append(None)
        self.userscore.append(None)
        #set user status not playing
        self.statusPlayingUser[user]=False
        #a dictionary contain user's protocol
        self.protocoldict[user]=protocol
        #response
        if len(self.userlist) == 1:
            self.addResponse((user,res.NOTIFY_CREATE_OK))
            self.host = user
        elif len(self.userlist) > 1:
            self.addResponse((user,res.NOTIFY_JOIN_OK))     
        strlist = ""
        for user in self.userlist:
            strlist = strlist + user + " "                    
        self.broadcast(res.NOTIFY_USER_LIST+ " " + strlist.strip()) 
        self.broadcast(res.NOTIFY_USER_HOST+ " " + self.host)
        if self.status == "playing":
            self.addResponse((user,res.NOTIFY_GAME_PLAYING))
        else:
            self.addResponse((user,res.NOTIFY_GAME_WAITING))
        return True

    def part(self,user):
        global notify
        res = notify
        try:
            #do finish action
            #self.pcuserFinish(user)
            #remove in currentlist
            self.userlistcurrent.remove(user)
        except:
            pass
        
        try:
            i = self.userlist.index(user)
        except:
            i = -1
        ishost = False
        if i <> -1:
            if self.userlist[i] == self.host:
                ishost = True
            #remove data
            del self.protocoldict[self.userlist[i]]
            #remove in userlist
            del self.userlist[i]
            del self.usercards[i]
            del self.userscore[i]
            del self.statusPlayingUser[user]
            #if host part room, next user will be host
            if ishost:
                if len(self.userlist)>0:
                    self.host = self.userlist[0]                    
                    self.broadcast(res.NOTIFY_USER_HOST+ " " + self.host)
            #if noone in room, stop thread
            if len(self.userlist) == 0:
                self.stop()
            if len(self.userlist) == 1:
                self.status = "waiting"      
            #update userlist
            strlist = ""
            for user in self.userlist:
                strlist = strlist + user + " "                        
            self.broadcast(res.NOTIFY_USER_LIST+ " " + strlist.strip())
            return True
        else:
            return False 

    def getUserMoney(self,user):
        return 100000



class CardGame(GameThread):
    RequestList = []
    ResponseList = []
    MAX_USER = 10        
    def __init__(self,host=None,betmoney=None,password=None):
        self.userlist = []
        self.userlistcurrent = []        
        self.authenticated = False
        self.usercards = []
        self.userscore = []
        self.userwinners = []
        self.deck = []
        self.status = None
        #self.statusUser = dict()
        self.statusPlayingUser = dict()
        self.protocoldict = dict()
        self.host = host
        self.currentturn = -1
        self.betmoney = betmoney
        self.password = password
        GameThread.__init__(self)        
        self.initdeck()

    def initdeck(self):
        ishuffle = 30
        random.seed()
        for i in range(0,52):
            self.deck.append(i+1)
        #scramble
        for j in range(ishuffle):
            i1 = random.randint(0,51)
            i2 = random.randint(0,51)
            while (i2 == i1):
                i2 = random.randint(0,51)
            self.deck[i1],self.deck[i2]=self.deck[i2],self.deck[i1]        

    def addRequest(self,request):
        self.RequestList.append(request)
        
    def addResponse(self,response):
        self.ResponseList.append(response)
    
    
    def processResponse(self):
        if len(self.ResponseList)>0:
            queue = deque(self.ResponseList)
            while True:
                try:                
                    user,res = queue.popleft()
                    if self.protocoldict.has_key(user):
                        self.protocoldict[user].response(res)
                except Exception as err:
                    break
            del self.ResponseList[:]    

    def join(self,user,protocol,password):
        global notify
        res = notify
        #check password
        if self.password:
            if password <> self.password:
                return False
        #check max user
        if len(self.userlist)>=self.MAX_USER:
            return False
        #append user in list                                
        self.userlist.append(user)
        self.usercards.append(None)
        self.userscore.append(None)
        #set user status not playing
        self.statusPlayingUser[user]=False
        #a dictionary contain user's protocol
        self.protocoldict[user]=protocol
        #response
        if len(self.userlist) == 1:
            self.addResponse((user,res.NOTIFY_CREATE_OK))
            self.host = user
        elif len(self.userlist) > 1:
            self.addResponse((user,res.NOTIFY_JOIN_OK))     
        strlist = ""
        for user in self.userlist:
            strlist = strlist + user + " "                    
        self.broadcast(res.NOTIFY_USER_LIST+ " " + strlist.strip()) 
        self.broadcast(res.NOTIFY_USER_HOST+ " " + self.host)
        if self.status == "playing":
            self.addResponse((user,res.NOTIFY_GAME_PLAYING))
        else:
            self.addResponse((user,res.NOTIFY_GAME_WAITING))
        return True

    def part(self,user):
        global notify
        res = notify
        try:
            #do finish action
            #self.pcuserFinish(user)
            #remove in currentlist
            self.userlistcurrent.remove(user)
        except:
            pass
        
        try:
            i = self.userlist.index(user)
        except:
            i = -1
        ishost = False
        if i <> -1:
            if self.userlist[i] == self.host:
                ishost = True
            #remove data
            del self.protocoldict[self.userlist[i]]
            #remove in userlist
            del self.userlist[i]
            del self.usercards[i]
            del self.userscore[i]
            del self.statusPlayingUser[user]
            #if host part room, next user will be host
            if ishost:
                if len(self.userlist)>0:
                    self.host = self.userlist[0]                    
                    self.broadcast(res.NOTIFY_USER_HOST+ " " + self.host)
            #if noone in room, stop thread
            if len(self.userlist) == 0:
                self.stop()            
            #update userlist
            strlist = ""
            for user in self.userlist:
                strlist = strlist + user + " "                        
            self.broadcast(res.NOTIFY_USER_LIST+ " " + strlist.strip())
            return True
        else:
            return False 

    def getUserMoney(self,user):
        return 100000                     
    